<!-- Chat.vue -->
<template>
  <div class="chat-interface">
    <!-- 聊天消息区域 -->
    <div class="chat-messages" ref="messagesContainer">
      <div v-if="loading" class="loading-messages">
        <el-skeleton :rows="3" animated/>
      </div>

      <template v-else>
        <div v-for="(message, index) in messages"
             :key="index"
             :class="['message-item', message.role, { 'streaming': message.isStreaming }]">
          <div class="avatar">
            <el-avatar
                :size="40"
                :src="message.role === 'user' ? userAvatar : aiAvatar"
                @error="() => message.role === 'user' ? userAvatarError = true : aiAvatarError = true">
              <span v-if="message.role === 'user' && userAvatarError">{{
                  userName?.charAt(0)?.toUpperCase() || 'U'
                }}</span>
              <span v-if="message.role === 'assistant' && aiAvatarError">A</span>
            </el-avatar>
          </div>

          <div class="message-content">
            <!-- 文件消息显示 -->
            <template v-if="message.isFile">
              <div class="files-container">
                <div class="file-item">
                  <div class="file-card" @click="viewMessageFile(message)">
                    <div class="file-card-icon">
                      <el-icon v-if="message.fileInfo?.type.startsWith('image/')">
                        <Picture/>
                      </el-icon>
                      <el-icon v-else-if="message.fileInfo?.type === 'application/pdf'">
                        <Document/>
                      </el-icon>
                      <el-icon v-else-if="message.fileInfo?.type.startsWith('video/')">
                        <VideoPlay/>
                      </el-icon>
                      <el-icon v-else-if="message.fileInfo?.type.startsWith('audio/')">
                        <Headset/>
                      </el-icon>
                      <el-icon
                          v-else-if="message.fileInfo?.type.startsWith('text/') || ['application/json', 'application/xml', 'application/javascript'].includes(message.fileInfo?.type)">
                        <Document/>
                      </el-icon>
                      <el-icon v-else>
                        <Files/>
                      </el-icon>
                    </div>
                    <div class="file-card-content">
                      <div class="file-card-name" :title="message.fileInfo?.name">{{ message.fileInfo?.name }}</div>
                      <div class="file-card-info">
                        <span class="file-type">{{ getMessageFileType(message) }}</span>
                        <span class="file-divider">·</span>
                        <span class="file-size">{{ formatFileSize(message.fileInfo?.size) }}</span>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </template>
            <!-- 显示消息中的files属性 -->
            <template v-else-if="message.isFileMessage && message.files && message.files.length > 0">
              <div class="files-container">
                <div v-for="(file, fileIndex) in message.files" :key="fileIndex" class="file-item">
                  <div class="file-card" @click="viewFile(file)">
                    <div class="file-card-icon">
                      <el-icon v-if="file.type.startsWith('image/')">
                        <Picture/>
                      </el-icon>
                      <el-icon v-else-if="file.type === 'application/pdf'">
                        <Document/>
                      </el-icon>
                      <el-icon v-else-if="file.type.startsWith('video/')">
                        <VideoPlay/>
                      </el-icon>
                      <el-icon v-else-if="file.type.startsWith('audio/')">
                        <Headset/>
                      </el-icon>
                      <el-icon
                          v-else-if="file.type.startsWith('text/') || ['application/json', 'application/xml', 'application/javascript'].includes(file.type)">
                        <Document/>
                      </el-icon>
                      <el-icon v-else>
                        <Files/>
                      </el-icon>
                    </div>
                    <div class="file-card-content">
                      <div class="file-card-name" :title="file.name">{{ file.name }}</div>
                      <div class="file-card-info">
                        <span class="file-type">{{ getFileTypeName({type: file.type}) }}</span>
                        <span class="file-divider">·</span>
                        <span class="file-size">{{ formatFileSize(file.size) }}</span>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <div v-if="message.content" class="message-text" v-html="formatMessage(message.content)"></div>
            </template>
            <!-- 普通消息显示 -->
            <template v-else>
              <div class="message-text" v-html="formatMessage(message.content)"></div>
              <div v-if="message.isStreaming" class="streaming-indicator">AI 正在输入中...</div>
              <div v-else-if="message.role === 'assistant'" class="message-actions">
                <el-button text size="small" @click="copyMessage(message.content)">
                  <el-icon>
                    <DocumentCopy/>
                  </el-icon>
                  复制
                </el-button>
              </div>
            </template>
          </div>
        </div>

        <div v-if="messages.length === 0" class="empty-messages">
          <el-empty description="开始新的对话吧"/>
        </div>
      </template>
    </div>

    <!-- 底部输入区域 -->
    <div class="chat-input-area">
      <!-- 已上传文件预览 -->
      <div v-if="uploadedFiles.length > 0" class="uploaded-files-preview">
        <div v-for="(file, index) in uploadedFiles" :key="index" class="file-card" @click="previewFile(file)">
          <div class="file-card-icon">
            <el-icon v-if="file.type.startsWith('image/')">
              <Picture/>
            </el-icon>
            <el-icon v-else-if="file.type === 'application/pdf'">
              <Document/>
            </el-icon>
            <el-icon v-else-if="file.type.startsWith('video/')">
              <VideoPlay/>
            </el-icon>
            <el-icon v-else-if="file.type.startsWith('audio/')">
              <Headset/>
            </el-icon>
            <el-icon
                v-else-if="file.type.startsWith('text/') || ['application/json', 'application/xml', 'application/javascript'].includes(file.type)">
              <Document/>
            </el-icon>
            <el-icon v-else>
              <Files/>
            </el-icon>
          </div>
          <div class="file-card-content">
            <div class="file-card-name" :title="file.name">{{ file.name }}</div>
            <div class="file-card-info">
              <span class="file-type">{{ getFileTypeName(file) }}</span>
              <span class="file-divider">·</span>
              <span class="file-size">{{ formatFileSize(file.size) }}</span>
            </div>
          </div>
          <div class="file-card-delete" @click.stop="removeFile(index)">
            <i class="delete-icon">×</i>
          </div>
        </div>
      </div>

      <div class="input-wrapper">
        <textarea
            class="chat-input"
            placeholder="给 Sage 发送消息"
            v-model="inputMessage"
            @keydown.enter.prevent="sendMessage"
            ref="chatInput"
            @input="adjustInputHeight"
        ></textarea>
        <div class="tool-buttons">
          <div class="left-tools">
            <!-- 深度思考按钮 -->
            <button
                class="tool-btn deep-think"
                :class="{ 'active': isDeepThinking }"
                @click="toggleDeepThinking"
                :title="isDeepThinking ? '已启用深度思考模式' : '点击启用深度思考模式'">
              <span class="icon-deep-think"></span>
              深度思考{{ isDeepThinking ? ' (已启用)' : '' }}
            </button>

            <!--            &lt;!&ndash; 联网搜索按钮 &ndash;&gt;
            <button class="tool-btn web-search">
              <span class="icon-globe"></span>
              联网搜索
                        </button>-->
          </div>

          <div class="right-tools">
            <!-- 添加隐藏的文件输入 -->
            <input
                type="file"
                ref="fileInputRef"
                @change="handleFileUpload"
                multiple
                style="display: none"
            />
            <!-- 上传文件按钮 -->
            <button class="tool-btn upload" @click="triggerFileUpload">
              <span class="icon-upload"></span>
            </button>
            <!-- 发送按钮 -->
            <button
                class="tool-btn send"
                :disabled="(isLoading || (!inputMessage.trim() && uploadedFiles.length === 0))"
                @click="sendMessage">
              <span class="icon-send"></span>
            </button>
          </div>
        </div>
      </div>
    </div>
    <div class="warn-text">内容由Ai生成，请仔细甄别</div>
  </div>
</template>

<script setup>
import {ref, computed, onMounted, nextTick, watch, onUnmounted} from 'vue';
import {createVNode, render} from 'vue';
import {dayjs, ElMessage} from 'element-plus';
import userStore from '@/store/user';
import {
  DocumentCopy,
  Delete,
  Document,
  PictureFilled,
  VideoCamera,
  Headset,
  Files,
  DataAnalysis,
  Picture,
  VideoPlay,
  Upload
} from '@element-plus/icons-vue';
import {getChatMessages} from "@/api";
import {sendMsg} from "@/utils/sseClient";
import CodeBlock from './CodeBlock.vue';
import FileMessage from './FileMessage.vue';
import {v4 as uuidv4} from 'uuid';
import {upload} from "@/api/common";

const props = defineProps({
  sessionId: {
    type: [Number, String],
    required: true
  },
  initialMessages: {
    type: Array,
    default: () => []
  },
  userAvatar: {  // 添加这个props
    type: String,
    default: ''
  },
  handleSession: Function,

});


// 状态变量
const messages = ref([]);
const loading = ref(true);
const inputMessage = ref('');
const isLoading = ref(false);
const messagesContainer = ref(null);
const userAvatar = computed(() => props.userAvatar || require('@/assets/images/profile.jpg'));
const aiAvatar = ref(require('@/assets/images/ai.png'));
const userAvatarError = ref(false);
const aiAvatarError = ref(false);
const userName = computed(() => userStore.getUserName());
const controller = ref(null);
const isDeepThinking = ref(false); // 深度思考模式状态
// 添加fileStore变量的定义
const fileStore = ref({});
// 文件上传相关
const uploadedFiles = ref([]);
const fileInputRef = ref(null);

const chatInput = ref(null); // 添加输入框引用

// 流式响应相关
const isStreaming = ref(false);
const streamingContent = ref('');

// 文件相关工具函数
const getMessageFiles = (message) => {
  if (!message.isFileMessage || !message.content) return [];
  try {
    const content = JSON.parse(message.content);
    return content.type === 'files' ? content.files : [];
  } catch (e) {
    console.error('解析文件消息失败:', e);
    return [];
  }
};

// 文件大小格式化
const formatFileSize = (bytes) => {
  if (!bytes || bytes === 0) return '0 Bytes';
  const k = 1024;
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};

// 预览文件
const previewFile = (fileObj) => {
  // 检查是否是File对象或者包含url的对象
  const isFileObject = fileObj instanceof File;
  const url = isFileObject ? URL.createObjectURL(fileObj) : fileObj.url;

  if (!url) {
    ElMessage.error('无法获取文件URL');
    return;
  }

  // 获取文件类型
  const type = fileObj.type;

  // 图片文件
  if (type.startsWith('image/')) {
    // 创建modal预览
    const modal = document.createElement('div');
    modal.style.position = 'fixed';
    modal.style.top = '0';
    modal.style.left = '0';
    modal.style.width = '100%';
    modal.style.height = '100%';
    modal.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
    modal.style.zIndex = '9999';
    modal.style.display = 'flex';
    modal.style.justifyContent = 'center';
    modal.style.alignItems = 'center';
    modal.style.cursor = 'pointer';

    // 创建图片元素
    const img = document.createElement('img');
    img.src = url;
    img.style.maxWidth = '80%';
    img.style.maxHeight = '80%';
    img.style.objectFit = 'contain';
    modal.appendChild(img);

    // 关闭预览
    modal.onclick = () => {
      document.body.removeChild(modal);
      if (isFileObject) {
        URL.revokeObjectURL(url);
      }
    };

    document.body.appendChild(modal);
  }
  // PDF文件
  else if (type === 'application/pdf') {
    window.open(url, '_blank');
    // PDF在新窗口打开后释放URL
    if (isFileObject) {
      setTimeout(() => URL.revokeObjectURL(url), 1000);
    }
  }
  // 文本文件
  else if (type.startsWith('text/') ||
      ['application/json', 'application/xml', 'application/javascript'].includes(type)) {
    if (isFileObject) {
      const reader = new FileReader();
      reader.onload = (e) => {
        showTextPreview(e.target.result);
      };
      reader.readAsText(fileObj);
    } else {
      // 如果是URL，通过fetch获取内容
      fetch(url)
          .then(response => response.text())
          .then(text => {
            showTextPreview(text);
          })
          .catch(err => {
            ElMessage.error('无法加载文本内容');
            console.error(err);
          });
    }
  }
  // 视频文件
  else if (type.startsWith('video/')) {
    const modal = createMediaModal();

    const video = document.createElement('video');
    video.src = url;
    video.controls = true;
    video.autoplay = true;
    video.style.maxWidth = '80%';
    video.style.maxHeight = '80%';
    modal.appendChild(video);

    modal.onclick = (e) => {
      if (e.target === modal) {
        document.body.removeChild(modal);
        if (isFileObject) {
          URL.revokeObjectURL(url);
        }
      }
    };

    document.body.appendChild(modal);
  }
  // 音频文件
  else if (type.startsWith('audio/')) {
    const modal = createMediaModal();

    const audio = document.createElement('audio');
    audio.src = url;
    audio.controls = true;
    audio.autoplay = true;
    audio.style.width = '80%';
    modal.appendChild(audio);

    modal.onclick = (e) => {
      if (e.target === modal) {
        document.body.removeChild(modal);
        if (isFileObject) {
          URL.revokeObjectURL(url);
        }
      }
    };

    document.body.appendChild(modal);
  }
  // 其他文件类型
  else {
    if (fileObj.url) {
      window.open(fileObj.url, '_blank');
    } else {
      ElMessage.info('该文件类型无法预览');
      if (isFileObject) {
        URL.revokeObjectURL(url);
      }
    }
  }
};

// 创建媒体模态框
const createMediaModal = () => {
  const modal = document.createElement('div');
  modal.style.position = 'fixed';
  modal.style.top = '0';
  modal.style.left = '0';
  modal.style.width = '100%';
  modal.style.height = '100%';
  modal.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
  modal.style.zIndex = '9999';
  modal.style.display = 'flex';
  modal.style.justifyContent = 'center';
  modal.style.alignItems = 'center';
  return modal;
};

// 显示文本预览
const showTextPreview = (text) => {
  const modal = document.createElement('div');
  modal.style.position = 'fixed';
  modal.style.top = '0';
  modal.style.left = '0';
  modal.style.width = '100%';
  modal.style.height = '100%';
  modal.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
  modal.style.zIndex = '9999';
  modal.style.display = 'flex';
  modal.style.justifyContent = 'center';
  modal.style.alignItems = 'center';
  modal.style.cursor = 'pointer';

  // 创建文本容器
  const content = document.createElement('pre');
  content.textContent = text;
  content.style.maxWidth = '80%';
  content.style.maxHeight = '80%';
  content.style.overflow = 'auto';
  content.style.backgroundColor = '#282c34';
  content.style.color = '#abb2bf';
  content.style.padding = '20px';
  content.style.borderRadius = '5px';
  content.style.fontFamily = 'monospace';
  content.style.whiteSpace = 'pre-wrap';
  content.style.cursor = 'text';
  modal.appendChild(content);

  // 阻止点击内容时关闭模态框
  content.onclick = (e) => {
    e.stopPropagation();
  };

  // 关闭预览
  modal.onclick = () => {
    document.body.removeChild(modal);
  };

  document.body.appendChild(modal);
};

// 删除文件
const removeFile = (index) => {
  uploadedFiles.value.splice(index, 1);
  ElMessage.success('文件已移除');
};

// 在脚本最开始就设置初始消息
messages.value = props.initialMessages.length > 0 ? props.initialMessages : [];

const adjustInputHeight = () => {
  if (!chatInput.value) return;

  // 重置高度，以便正确计算
  chatInput.value.style.height = 'auto';

  // 设置新高度 (scrollHeight 是内容的实际高度)
  const newHeight = Math.min(chatInput.value.scrollHeight, 200); // 最大高度限制为200px
  chatInput.value.style.height = `${newHeight}px`;
};
// 监听输入消息变化，调整高度
watch(inputMessage, () => {
  nextTick(() => {
    adjustInputHeight();
  });
});

const getChatSession = (message, files = []) => {
  const now = dayjs().format('YYYY-MM-DD HH:mm:ss');

  // 创建第一条用户消息
  const firstMessage = {
    role: 'user',
    content: message,
    createTime: now,
    createBy: userStore.getUserName(),
    updateBy: userStore.getUserName(), 
    updateTime: now,
    userId: userStore.getUserId(),
    isFileMessage: files && files.length > 0,
    files: files && files.length > 0 ? files.map(file => ({
      name: file.name,
      type: file.type,
      size: file.size,
      url: file.url,
      path:file.path,
      newFileName: file.newFileName,
      originalFilename: file.originalFilename || file.name,
    })) : []
  };

  // 创建会话对象
  const session = {
    userId: userStore.getUserId(),
    createBy: userStore.getUserName(),
    createTime: now,
    updateBy: userStore.getUserName(),
    updateTime: now,
    messages: [firstMessage],
    content: message,
    sessionId: props.sessionId,
    deepThinking: isDeepThinking.value // 添加深度思考模式标记
  };

  return session;
};

// 格式化消息文本
const formatMessage = (content) => {
  if (!content) return '';

  // 处理代码块
  const codeBlockRegex = /```([a-zA-Z]*)(:[^\n]*)?\n([\s\S]*?)```/g;
  let formattedContent = content;
  let match;
  let codeBlocks = [];

  // 提取所有代码块
  while ((match = codeBlockRegex.exec(content)) !== null) {
    const language = match[1] || 'plaintext';
    const fileName = match[2] ? match[2].substring(1).trim() : '';
    const code = match[3];
    const placeholder = `__CODE_BLOCK_${codeBlocks.length}__`;

    codeBlocks.push({
      language,
      fileName,
      code,
      placeholder
    });

    formattedContent = formattedContent.replace(match[0], placeholder);
  }

  // 处理普通文本（换行等）
  formattedContent = formattedContent.replace(/\n/g, '<br>');

  // 将代码块占位符替换为组件
  for (const block of codeBlocks) {
    const componentHtml = `<div class="code-block-wrapper" data-language="${block.language}" data-filename="${block.fileName}" data-code="${encodeURIComponent(block.code)}"></div>`;
    formattedContent = formattedContent.replace(block.placeholder, componentHtml);
  }

  return formattedContent;
};

// 在消息渲染后处理代码块
const processCodeBlocks = () => {
  nextTick(() => {
    const codeBlockWrappers = document.querySelectorAll('.code-block-wrapper');
    codeBlockWrappers.forEach(wrapper => {
      const language = wrapper.getAttribute('data-language');
      const fileName = wrapper.getAttribute('data-filename');
      const code = decodeURIComponent(wrapper.getAttribute('data-code'));

      // 创建代码块组件实例
      const codeBlockInstance = createVNode(CodeBlock, {
        code,
        language,
        fileName
      });

      // 渲染组件
      render(codeBlockInstance, wrapper);
    });
  });
};

// 监听消息变化，处理代码块
watch(() => messages.value, () => {
  processCodeBlocks();
}, {deep: true});

// 在组件挂载时处理代码块
onMounted(() => {
  nextTick(() => {
    adjustInputHeight();
    processCodeBlocks();
  });
});

// 复制消息
const copyMessage = (content) => {
  navigator.clipboard.writeText(content)
      .then(() => {
        ElMessage.success('已复制到剪贴板');
      })
      .catch(() => {
        ElMessage.error('复制失败');
      });
};

// 滚动到底部
const scrollToBottom = () => {
  nextTick(() => {
    if (messagesContainer.value) {
      messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight;
    }
  });
};

// 添加一个公开方法，用于从外部追加流式内容
const appendStreamingContent = (chunk) => {
  // 如果没有正在流式传输的消息，创建一个
  if (!isStreaming.value) {
    isStreaming.value = true;
    streamingContent.value = '';

    // 添加一个临时的 AI 消息
    messages.value.push({
      role: 'assistant',
      content: '',
      createTime: new Date().toISOString(),
      isStreaming: true
    });
  }

  // 追加内容
  streamingContent.value += chunk;

  // 更新最后一条消息的内容
  const lastIndex = messages.value.length - 1;
  if (lastIndex >= 0 && messages.value[lastIndex].role === 'assistant') {
    messages.value[lastIndex].content = streamingContent.value;
  }

  // 滚动到底部
  scrollToBottom();
};

// 添加一个方法，用于完成流式传输
const completeStreaming = () => {
  if (isStreaming.value) {
    isStreaming.value = false;

    // 更新最后一条消息，移除 isStreaming 标记
    const lastIndex = messages.value.length - 1;
    if (lastIndex >= 0 && messages.value[lastIndex].role === 'assistant') {
      messages.value[lastIndex] = {
        ...messages.value[lastIndex],
        content: streamingContent.value,
        isStreaming: false
      };
    }

    // 重置流式内容
    streamingContent.value = '';
  }
};

// 处理文件上传
const handleFileUpload = async (event) => {
  const newFiles = Array.from(event.target.files);
  if (newFiles.length === 0) return;

  try {
    for (const file of newFiles) {
      // 检查文件大小，限制为20MB
      if (file.size > 20 * 1024 * 1024) {
        ElMessage.warning(`文件 ${file.name} 超过20MB限制，已忽略`);
        continue;
      }

      // 创建FormData对象
      const formData = new FormData();
      formData.append('file', file);

      // 调用上传API
      const response = await upload(formData);

      if (response.code === 200) {
        // 上传成功，创建文件对象
        const fileInfo = {
          name: file.name,
          size: file.size,
          type: file.type,
          lastModified: file.lastModified,
          path: response.fileName,
          url: response.url,
          newFileName: response.newFileName,
          originalFilename: response.originalFilename
        };

        // 检查是否已存在同名文件，如果存在则替换
        const existingFileIndex = uploadedFiles.value.findIndex(f => f.name === file.name);
        if (existingFileIndex !== -1) {
          uploadedFiles.value.splice(existingFileIndex, 1, fileInfo);
          ElMessage.info(`已替换同名文件: ${file.name}`);
        } else {
          uploadedFiles.value.push(fileInfo);
        }

        ElMessage.success(`文件 ${file.name} 上传成功`);
      } else {
        ElMessage.error(`文件 ${file.name} 上传失败: ${response.msg}`);
      }
    }

    // 清空文件输入，以便可以再次选择相同的文件
    event.target.value = '';

    // 上传后重新聚焦到输入框
    chatInput.value?.focus();
  } catch (error) {
    console.error('文件上传失败:', error);
    ElMessage.error('文件上传失败，请重试');
    // 清空文件输入
    event.target.value = '';
  }
};

// 触发文件选择对话框
const triggerFileUpload = () => {
  if (fileInputRef.value) {
    fileInputRef.value.click();
  }
};

// 发送消息函数
const sendMessage = async () => {
  const text = inputMessage.value.trim();
  const hasFiles = uploadedFiles.value.length > 0;

  if (!text && !hasFiles || isLoading.value) return;

  try {
    isLoading.value = true;

    // 文件集合，将被显示并传递给AI
    const fileInfos = [];

    // 如果有文件
    if (hasFiles) {
      // 处理文件信息
      uploadedFiles.value.forEach(fileInfo => {
        fileInfos.push({
          name: fileInfo.name,
          size: fileInfo.size,
          type: fileInfo.type,
          url: fileInfo.url,
          path:fileInfo.path,
          newFileName: fileInfo.newFileName,
          originalFilename: fileInfo.originalFilename
        });
      });
    }

    // 添加用户消息
    const userMessage = {
      role: 'user',
      content: text || "请分析这些文件",
      createTime: new Date().toISOString(),
      deepThinking: isDeepThinking.value,
      isFileMessage: hasFiles,
      files: fileInfos
    };
    // 如果有文件，添加文件信息到UI显示
    if (hasFiles) {
      fileInfos.forEach(fileInfo => {
        const fileMessageId = uuidv4();
        // 保存文件引用以便在UI中显示
        fileStore.value[fileMessageId] = fileInfo;
        
        // 添加文件信息到UI显示
        messages.value.push({
          id: fileMessageId,
          role: 'user',
          content: '',
          fileInfo: fileInfo,
          createTime: new Date().toISOString(),
          isFile: true
        });
      });
    }
    
    // 添加用户消息到UI
    messages.value.push(userMessage);

    // 准备聊天会话数据
    let chatSession = getChatSession(text || "请分析这些文件", fileInfos);

    // 清空输入框和文件列表
    inputMessage.value = '';
    uploadedFiles.value = [];

    // 开始流式传输响应前准备
    isStreaming.value = true;
    streamingContent.value = '';

    // 添加临时AI消息占位
    messages.value.push({
      role: 'assistant',
      content: '',
      createTime: new Date().toISOString(),
      isStreaming: true,
      deepThinking: isDeepThinking.value
    });

    // 如果是深度思考模式，显示特殊提示
    if (isDeepThinking.value) {
      appendStreamingContent("🧠 深度思考模式：正在更全面地分析您的问题...\n\n");
    }

    // 发送消息并接收流式响应
    sendMsg(chatSession, {
      onSessionId: (sessionId) => {
        console.log(sessionId);
      },
      onMessage: (chunk) => {
        // 累积AI回复并更新界面
        appendStreamingContent(chunk);
      },
      onComplete: () => {
        // 完成流式传输
        completeStreaming();
        // 关闭加载状态
        isLoading.value = false;
      },
      onError: (error) => {
        console.error("创建会话失败:", error);
        ElMessage.error("创建会话失败，请重试");

        // 移除正在流式传输的消息
        if (isStreaming.value) {
          const lastIndex = messages.value.length - 1;
          if (lastIndex >= 0 && messages.value[lastIndex].role === 'assistant') {
            messages.value.pop();
          }
          isStreaming.value = false;
          streamingContent.value = '';
        }

        // 关闭加载状态
        isLoading.value = false;
      }
    });

    // 滚动到底部
    scrollToBottom();
  } catch (error) {
    console.error('发送消息失败:', error);
    ElMessage.error('发送消息失败');

    // 清理状态
    isLoading.value = false;
    if (isStreaming.value) {
      const lastIndex = messages.value.length - 1;
      if (lastIndex >= 0 && messages.value[lastIndex].role === 'assistant') {
        messages.value.pop();
      }
      isStreaming.value = false;
      streamingContent.value = '';
    }
  }
};

// 修改加载消息方法
const loadMessages = async () => {
  // 如果已经有初始消息，则不需要请求
  if (props.initialMessages.length > 0) {
    messages.value = props.initialMessages;
    loading.value = false;
    scrollToBottom();
    return;
  }

  try {
    loading.value = true;

    // 根据新API获取消息
    const response = await getChatMessages(props.sessionId);
    if (response.code === 200 && response.data) {
      messages.value = response.data.messages || [];
      scrollToBottom();
    } else {
      ElMessage.error(response.msg || '获取聊天记录失败');
    }
  } catch (error) {
    console.error('加载聊天记录失败:', error);
    ElMessage.error('加载聊天记录失败');
  } finally {
    loading.value = false;
  }
};


// 在组件挂载时加载聊天消息
onMounted(async () => {
  nextTick(() => {
    adjustInputHeight();
  });
});

// 监听sessionId变化，重新加载消息
watch(() => props.sessionId, async (newId) => {
  if (newId) {
    loading.value = true;
    messages.value = props.initialMessages.length > 0 ? props.initialMessages : [];

    // 只在没有初始消息时加载
    if (props.initialMessages.length === 0) {
      await loadMessages();
    }

    loading.value = false;
    scrollToBottom();
  }
}, {immediate: true});

// 组件卸载时清理
onUnmounted(() => {
  if (controller.value) {
    controller.value.abort();
    controller.value = null;
  }
});

// 暴露方法给父组件
defineExpose({
  appendStreamingContent,
  completeStreaming
});

// 切换深度思考模式
const toggleDeepThinking = () => {
  isDeepThinking.value = !isDeepThinking.value;
  if (isDeepThinking.value) {
    ElMessage.success('已启用深度思考模式，AI将花更多时间思考您的问题');
  } else {
    ElMessage.info('已关闭深度思考模式');
  }
};

// 根据文件类型获取类型名称
const getFileTypeName = (file) => {
  if (file.type.startsWith('image/')) {
    return '图片';
  } else if (file.type === 'application/pdf') {
    return 'PDF';
  } else if (file.type.startsWith('video/')) {
    return '视频';
  } else if (file.type.startsWith('audio/')) {
    return '音频';
  } else if (file.type.startsWith('text/')) {
    return '文本';
  } else if (['application/json', 'application/xml', 'application/javascript'].includes(file.type)) {
    return file.type.split('/')[1].toUpperCase();
  } else {
    // 获取文件扩展名
    const extension = file.name.split('.').pop()?.toUpperCase();
    return extension || '文件';
  }
};

// 获取消息中文件的类型
const getMessageFileType = (message) => {
  if (!message.fileInfo) return '文件';

  const fileType = message.fileInfo.type;
  if (fileType.startsWith('image/')) {
    return '图片';
  } else if (fileType === 'application/pdf') {
    return 'PDF';
  } else if (fileType.startsWith('video/')) {
    return '视频';
  } else if (fileType.startsWith('audio/')) {
    return '音频';
  } else if (fileType.startsWith('text/')) {
    return '文本';
  } else if (['application/json', 'application/xml', 'application/javascript'].includes(fileType)) {
    return fileType.split('/')[1].toUpperCase();
  } else {
    // 获取文件扩展名
    const extension = message.fileInfo.name.split('.').pop()?.toUpperCase();
    return extension || '文件';
  }
};

// 查看消息中的文件
const viewMessageFile = (message) => {
  if (!message.fileInfo) return;

  // 从fileStore中获取文件或直接使用fileInfo
  const fileObj = fileStore.value[message.id] || message.fileInfo;

  if (fileObj) {
    previewFile(fileObj);
  } else {
    ElMessage.info('无法预览该文件，文件引用已失效');
  }
};

// 查看files数组中的文件
const viewFile = (file) => {
  if (!file) return;
  
  // 构建完整的文件URL
  const fileObj = {
    ...file,
    url: getCompleteFileUrl(file.url)
  };
  
  previewFile(fileObj);
};

// 获取完整的文件URL
const getCompleteFileUrl = (url) => {
  if (!url) return '';
  
  // 如果已经是完整URL，则直接返回
  if (url.startsWith('http://') || url.startsWith('https://')) {
    return url;
  }
  
  // 如果是相对路径，添加base URL
  if (url.startsWith('/')) {
    return import.meta.env.VITE_APP_BASE_API + url;
  }
  
  // 如果需要添加/profile前缀
  if (!url.startsWith('/profile')) {
    return import.meta.env.VITE_APP_BASE_API + '/profile/' + url;
  }
  
  return import.meta.env.VITE_APP_BASE_API + url;
};
</script>

<style scoped>
/* 聊天界面样式 */
.chat-interface {
  display: flex;
  flex-direction: column;
  height: 100%;
  background-color: #f0f5ff;
  overflow: hidden; /* 防止容器本身出现滚动条 */
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-bottom: 10px; /* 为底部输入框留出空间 */
  width: 800px; /* 与input-wrapper保持一致 */
  margin-left: auto;
  margin-right: auto;
  padding: 20px 0; /* 修改padding，保留上下内边距，去掉左右内边距 */

  /* 隐藏滚动条 - 各浏览器兼容 */
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE and Edge */
}

/* Webkit 浏览器（Chrome、Safari等）隐藏滚动条 */
.chat-messages::-webkit-scrollbar {
  display: none;
}

.loading-messages {
  padding: 20px;
  background-color: rgba(255, 255, 255, 0.6);
  border-radius: 8px;
}

.empty-messages {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #909399;
}

.message-item {
  display: flex;
  margin-bottom: 16px;
  animation: fade-in 0.3s ease;
  width: 100%;
  padding: 0 20px; /* 添加左右padding到消息项 */
}

.message-item.user {
  flex-direction: row-reverse;
}

.avatar {
  flex-shrink: 0;
  margin: 0 12px;
}

.message-content {
  max-width: calc(100% - 80px); /* 修改最大宽度计算，考虑头像和边距 */
  padding: 12px 16px;
  border-radius: 12px;
  position: relative;
}

.user .message-content {
  background-color: #2c56a0;
  color: white;
  border-radius: 12px 2px 12px 12px;
  margin-right: 8px;
}

.assistant .message-content {
  background-color: white;
  color: #2a3547;
  border-radius: 2px 12px 12px 12px;
  margin-left: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}

.message-text {
  line-height: 1.6;
  word-break: break-word;
}

.message-actions {
  margin-top: 8px;
  display: flex;
  justify-content: flex-end;
  opacity: 0.6;
  transition: opacity 0.2s;
}

.message-item:hover .message-actions {
  opacity: 1;
}

/* 聊天界面底部输入区域 */
.chat-input-area {
  background-color: transparent;
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin-bottom: 10px;
}

/* 输入框样式 */
.input-wrapper {
  width: 800px;
  background-color: #ffffff;
  padding: 14px 18px;
  margin: 0 auto;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  border: 1px solid rgba(0, 0, 0, 0.1);
}

.chat-input {
  width: 100%;
  min-height: 20px;
  padding: 0 14px;
  background: transparent;
  border: none;
  color: #2a3547;
  font-size: 16px;
  outline: none;
  line-height: 1.5;
  border-radius: 24px;
  overflow-y: hidden;

  /* 自动调整高度相关 */
  resize: none;
  max-height: 200px; /* 最大高度（避免无限增高） */
  transition: height 0.2s; /* 高度变化过渡效果（可选） */

  /* 隐藏滚动条 - 各浏览器兼容 */
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE and Edge */
}

/* Webkit 浏览器（Chrome、Safari等）隐藏滚动条 */
.chat-input::-webkit-scrollbar {
  display: none;
}

.chat-input::placeholder {
  color: #bbc0ca;
}

.tool-buttons {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-top: 1px solid rgba(44, 86, 160, 0.08);
}

.left-tools, .right-tools {
  display: flex;
  gap: 12px;
  align-items: center;
}

.tool-btn {
  display: flex;
  align-items: center;
  background: none;
  border: none;
  color: #5a6a85;
  font-size: 14px;
  padding: 8px 14px;
  border-radius: 12px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.tool-btn:hover {
  background-color: rgba(44, 86, 160, 0.05);
  transform: translateY(-1px);
}

.tool-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.tool-btn:disabled:hover {
  background-color: transparent;
  transform: none;
}

.deep-think {
  border: 1px solid rgba(44, 86, 160, 0.18);
  background-color: transparent;
  color: #5a6a85;
}

.deep-think:hover {
  background-color: rgba(44, 86, 160, 0.05);
}

/* 深度思考激活状态 */
.deep-think.active {
  background-color: rgba(44, 86, 160, 0.15);
  color: #2c56a0;
  border-color: rgba(44, 86, 160, 0.4);
  font-weight: 500;
}

.deep-think.active .icon-deep-think {
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%232c56a0"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-13h2v6h-2zm0 8h2v2h-2z"/></svg>');
}

.web-search {
  border: 1px solid rgba(44, 86, 160, 0.18);
}

.icon-deep-think, .icon-globe, .icon-upload, .icon-send {
  display: inline-block;
  width: 20px;
  height: 20px;
  margin-right: 8px;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}

.icon-deep-think {
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%235a6a85"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-13h2v6h-2zm0 8h2v2h-2z"/></svg>');
}

.icon-globe {
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%235a6a85"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>');
}

.icon-upload {
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%235a6a85"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"/></svg>');
}

.icon-send {
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%232c56a0"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>');
  transform: rotate(-45deg);
}

/* 流式传输相关样式 */
.streaming-indicator {
  font-size: 12px;
  color: #909399;
  margin-top: 8px;
  display: flex;
  align-items: center;
}

.streaming-indicator::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  background-color: #2c56a0;
  border-radius: 50%;
  margin-right: 8px;
  animation: pulse 1.5s infinite;
}

.message-item.streaming .message-text::after {
  content: '▋';
  display: inline-block;
  color: #2c56a0;
  animation: blink 1s step-start infinite;
}

@keyframes pulse {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.2);
    opacity: 0.7;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

@keyframes blink {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 警告文本样式 */
.warn-text {
  font-size: 12px;
  color: #909399;
  text-align: center;
  padding: 8px 0;
  font-weight: 300;
  width: 800px;
  margin: 0 auto;
}

/* 文件上传相关样式 */
.uploaded-files-preview {
  background-color: transparent;
  margin: 0 auto 15px auto;
  width: 800px;
  padding: 0;
}

.file-card {
  display: flex;
  align-items: center;
  background-color: #f0f0f0;
  border-radius: 4px;
  padding: 10px 12px;
  margin-bottom: 8px;
  color: #333;
  position: relative;
  width: 100%;
  cursor: pointer;
  transition: background-color 0.2s;
}

.file-card:hover {
  background-color: #e6e6e6;
}

.file-card-icon {
  width: 40px;
  height: 40px;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 4px;
  margin-right: 12px;
  background-color: #2c56a0;
  color: #fff;
  position: relative;
  font-size: 20px;
}

.file-card-icon :deep(.el-icon) {
  font-size: 20px;
}

.text-document-icon {
  display: inline-block;
  width: 16px;
  height: 18px;
  background-color: white;
  border-radius: 1px;
  position: relative;
}

.text-document-icon:before {
  content: "";
  position: absolute;
  top: 5px;
  left: 3px;
  width: 10px;
  height: 1.5px;
  background-color: #4aa4f6;
}

.text-document-icon:after {
  content: "";
  position: absolute;
  top: 9px;
  left: 3px;
  width: 10px;
  height: 1.5px;
  background-color: #4aa4f6;
}

.file-card-content {
  flex: 1;
  overflow: hidden;
  cursor: pointer;
}

.file-card-name {
  font-size: 14px;
  font-weight: 500;
  color: #333;
  margin-bottom: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.file-card-info {
  display: flex;
  align-items: center;
  font-size: 12px;
  color: #a1a6af;
}

.file-divider {
  margin: 0 4px;
}

.file-card-delete {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.2s, background-color 0.2s;
}

.file-card:hover .file-card-delete {
  opacity: 1;
}

.file-card-delete:hover {
  background-color: rgba(255, 0, 0, 0.7);
}

.delete-icon {
  font-style: normal;
  font-size: 14px;
  color: white;
  line-height: 1;
}

.file-item {
  width: 100%;
  max-width: 300px;
}

.message-item.user .file-item .file-card {
  background-color: #2c56a0;
  color: white;
}

.message-item.user .file-item .file-card-name {
  color: white;
}

.message-item.user .file-item .file-card-info {
  color: rgba(255, 255, 255, 0.7);
}

.message-item.assistant .file-item .file-card {
  background-color: white;
  color: #2a3547;
}
</style>